From: Keir Fraser Date: Thu, 13 May 2010 07:56:10 +0000 (+0100) Subject: VPMU: Enable vpmu for svm X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~12173 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22Dat/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22Dat?a=commitdiff_plain;h=d27901d494583f9098ceabbe1fd9593f546b8a31;p=xen.git VPMU: Enable vpmu for svm Signed-off-by: Wei Wang --- diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 1f527a8222..4231079d13 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -639,6 +639,7 @@ static void svm_ctxt_switch_from(struct vcpu *v) svm_fpu_leave(v); svm_save_dr(v); + vpmu_save(v); svm_sync_vmcb(v); svm_vmload(root_vmcb[cpu]); @@ -679,6 +680,7 @@ static void svm_ctxt_switch_to(struct vcpu *v) svm_vmsave(root_vmcb[cpu]); svm_vmload(v->arch.hvm_svm.vmcb); + vpmu_load(v); if ( cpu_has_rdtscp ) wrmsrl(MSR_TSC_AUX, hvm_msr_tsc_aux(v)); @@ -742,12 +744,15 @@ static int svm_vcpu_initialise(struct vcpu *v) return rc; } + vpmu_initialise(v); return 0; } static void svm_vcpu_destroy(struct vcpu *v) { svm_destroy_vmcb(v); + vpmu_destroy(v); + passive_domain_destroy(v); } static void svm_inject_exception( @@ -810,7 +815,7 @@ static int svm_event_pending(struct vcpu *v) static int svm_do_pmu_interrupt(struct cpu_user_regs *regs) { - return 0; + return vpmu_do_interrupt(regs); } static int svm_cpu_prepare(unsigned int cpu) @@ -1071,6 +1076,17 @@ static int svm_msr_read_intercept(struct cpu_user_regs *regs) msr_content = vmcb->lastinttoip; break; + case MSR_K7_PERFCTR0: + case MSR_K7_PERFCTR1: + case MSR_K7_PERFCTR2: + case MSR_K7_PERFCTR3: + case MSR_K7_EVNTSEL0: + case MSR_K7_EVNTSEL1: + case MSR_K7_EVNTSEL2: + case MSR_K7_EVNTSEL3: + vpmu_do_rdmsr(regs); + goto done; + default: if ( rdmsr_viridian_regs(ecx, &msr_content) || @@ -1089,6 +1105,7 @@ static int svm_msr_read_intercept(struct cpu_user_regs *regs) regs->eax = (uint32_t)msr_content; regs->edx = (uint32_t)(msr_content >> 32); +done: HVMTRACE_3D (MSR_READ, ecx, regs->eax, regs->edx); HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%x, eax=%lx, edx=%lx", ecx, (unsigned long)regs->eax, (unsigned long)regs->edx); @@ -1153,6 +1170,17 @@ static int svm_msr_write_intercept(struct cpu_user_regs *regs) vmcb->lastinttoip = msr_content; break; + case MSR_K7_PERFCTR0: + case MSR_K7_PERFCTR1: + case MSR_K7_PERFCTR2: + case MSR_K7_PERFCTR3: + case MSR_K7_EVNTSEL0: + case MSR_K7_EVNTSEL1: + case MSR_K7_EVNTSEL2: + case MSR_K7_EVNTSEL3: + vpmu_do_wrmsr(regs); + goto done; + default: if ( wrmsr_viridian_regs(ecx, msr_content) ) break; @@ -1169,7 +1197,7 @@ static int svm_msr_write_intercept(struct cpu_user_regs *regs) } break; } - +done: return X86EMUL_OKAY; gpf: diff --git a/xen/arch/x86/hvm/vpmu.c b/xen/arch/x86/hvm/vpmu.c index ac2129106f..48c34790a0 100644 --- a/xen/arch/x86/hvm/vpmu.c +++ b/xen/arch/x86/hvm/vpmu.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include static int __read_mostly opt_vpmu_enabled; boolean_param("vpmu", opt_vpmu_enabled); @@ -78,9 +80,14 @@ void vpmu_load(struct vcpu *v) } extern struct arch_vpmu_ops core2_vpmu_ops; +extern struct arch_vpmu_ops amd_vpmu_ops; + void vpmu_initialise(struct vcpu *v) { struct vpmu_struct *vpmu = vcpu_vpmu(v); + __u8 vendor = current_cpu_data.x86_vendor; + __u8 family = current_cpu_data.x86; + __u8 cpu_model = current_cpu_data.x86_model; if ( !opt_vpmu_enabled ) return; @@ -88,17 +95,45 @@ void vpmu_initialise(struct vcpu *v) if ( vpmu->flags & VPMU_CONTEXT_ALLOCATED ) vpmu_destroy(v); - if ( current_cpu_data.x86 == 6 ) + switch ( vendor ) { - switch ( current_cpu_data.x86_model ) + case X86_VENDOR_AMD: { - case 15: - case 23: - case 26: - case 29: - vpmu->arch_vpmu_ops = &core2_vpmu_ops; - break; + switch ( family ) + { + case 0x10: + vpmu->arch_vpmu_ops = &amd_vpmu_ops; + break; + default: + printk("VMPU: Initialization failed. " + "AMD processor family %d has not " + "been supported\n", family); + return; + } } + break; + + case X86_VENDOR_INTEL: + { + if ( family == 6 ) + { + switch ( cpu_model ) + { + case 15: + case 23: + case 26: + case 29: + vpmu->arch_vpmu_ops = &core2_vpmu_ops; + break; + } + } + } + break; + + default: + printk("VMPU: Initialization failed. " + "Unknown CPU vendor %d\n", vendor); + return; } if ( vpmu->arch_vpmu_ops != NULL ) diff --git a/xen/include/asm-x86/hvm/svm/svm.h b/xen/include/asm-x86/hvm/svm/svm.h index 9020aabffa..9a3743cc30 100644 --- a/xen/include/asm-x86/hvm/svm/svm.h +++ b/xen/include/asm-x86/hvm/svm/svm.h @@ -27,6 +27,7 @@ #include #include #include +#include void svm_dump_vmcb(const char *from, struct vmcb_struct *vmcb);